package com.leonardo.tg.example;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Vector;

import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

public class PersistCompromisso {

	private String storeId;
	private static RecordStore rs;
	
	public PersistCompromisso(String dbName) throws RecordStoreException {
		this.storeId = dbName;
		getRs();
	}
	
	public Integer numPersistedEntities() throws RecordStoreException {
		return new Integer(getRs().getNumRecords());
	}
	
	private RecordStore getRs() throws RecordStoreException {
		rs = RecordStore.openRecordStore(storeId, true);
		return rs;
	}
	
	public Compromisso getByKey(Integer key) throws RecordStoreException, IOException {
		if(key == null)
			throw new RuntimeException("Key cannot be null");
		byte[] compromissoArr = getRs().getRecord(key.intValue());
		Compromisso compromisso = deserialize(compromissoArr);
		return compromisso;
	}
	
	public Vector listAll() throws RecordStoreException, IOException {
		RecordEnumeration it = rs.enumerateRecords(null, null, false);
		Vector list = new Vector();
		while(it.hasNextElement())
			list.addElement(deserialize(it.nextRecord()));
		return list;
	}
	
	public void delete(Integer key) throws RecordStoreException {
		rs.deleteRecord(key.intValue());
	}
	
	public void clearDB() throws RecordStoreException {
		if(rs == null)
			return;
		rs.closeRecordStore();
		RecordStore.deleteRecordStore(storeId);
		rs = null;
	}
	
	public Integer persist(Compromisso compromisso) throws RecordStoreException, IOException {
		compromisso.setKey(new Integer(getRs().getNextRecordID()));
		byte[] record = serialize(compromisso);
		Integer key = new Integer(rs.addRecord(record, 0, record.length));
		return key;
	}
	
	public boolean offer(Compromisso compromisso) throws RecordStoreException, IOException {
		try {
			rs.getRecord(compromisso.getKey().intValue());
		} catch (InvalidRecordIDException e) {
			persist(compromisso);
			return true;
		} 
		return false;
	}
	
	public void update(Compromisso compromisso) throws RecordStoreException, IOException {
		if(compromisso.getKey() == null)
			throw new IllegalArgumentException("To update key cannot be null");
		byte[] record = serialize(compromisso);
		rs.setRecord(compromisso.getKey().intValue(), record, 0, record.length);
	}
	
	private Compromisso deserialize(byte[] record) throws IOException {
		ByteArrayInputStream bias = null;
		DataInputStream stream = null;
		
		try {
			bias = new ByteArrayInputStream(record);
			stream = new DataInputStream(bias); 
			Compromisso compromisso = new Compromisso();
			
			compromisso.setKey(new Integer(stream.readInt()));
			
			String nome = stream.readUTF();
			if(!nome.equals("!#null#!"))
				compromisso.setNome(nome);
			
			long date = stream.readLong();
			if(date != Long.MIN_VALUE)
				compromisso.setData(new Date(date));
			
			String descricao = stream.readUTF();
			if(!descricao.equals("!#null#!"))
				compromisso.setDescricao(descricao);
			
			Boolean confirmada = new Boolean(stream.readBoolean());
			compromisso.setConfirmada(confirmada);

			compromisso.setPrioridade(stream.readInt());
			
			Boolean completa = new Boolean(stream.readBoolean());
			compromisso.setCompleta(completa);
			
			return compromisso;
		} finally {
			try {
				bias.close();
				stream.close();
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private byte[] serialize(Compromisso compromisso) throws IOException {
		ByteArrayOutputStream bias = null;
		DataOutputStream stream = null;
		try {
			bias = new ByteArrayOutputStream();
			stream = new DataOutputStream(bias);
			
			stream.writeInt(compromisso.getKey().intValue());
			
			if(compromisso.getNome() == null)
				stream.writeUTF("!#null#!");
			else
				stream.writeUTF(compromisso.getNome());
			
			if(compromisso.getData() == null)
				stream.writeLong(Long.MIN_VALUE);
			else
				stream.writeLong(compromisso.getData().getTime());
			
			if(compromisso.getDescricao() == null)
				stream.writeUTF("!#null#!");
			else
				stream.writeUTF(compromisso.getDescricao());
			
			if(compromisso.getConfirmada() == null)
				stream.writeBoolean(false);
			else
				stream.writeBoolean(compromisso.getConfirmada().booleanValue());

			stream.writeInt(compromisso.getPrioridade());
			
			if(compromisso.getCompleta() == null)
				stream.writeBoolean(false);
			else
				stream.writeBoolean(compromisso.getCompleta().booleanValue());
			
			byte[] record = bias.toByteArray();
			return record;
		} finally {
			try {
				bias.close();
				stream.close();
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}
